package com.yf.ability.log;

import com.alibaba.fastjson.JSON;

import com.alibaba.fastjson.TypeReference;
import com.yf.ability.log.annon.LogInject;
import com.yf.ability.log.service.TopLogService;
import com.yf.ability.shiro.dto.SysUserLoginDTO;
import com.yf.base.api.api.ApiRest;
import com.yf.base.utils.IpUtils;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;

/**
 * 日志核心过滤器
 * @author bool
 */
@Log4j2
@Component
public class TopLogAspect {

    @Autowired
    private HttpServletRequest request;

    @Autowired
    private TopLogService topLogService;

    /**
     * 录制日志信息
     * @param jp
     * @return
     * @throws Throwable
     */
    public Object record(ProceedingJoinPoint jp) throws Throwable {

        // 请求地址
        String uri = request.getRequestURI();

        log.info("++++++++++注入日志信息：" + request.getRequestURI());

        // IP地址
        String ip = IpUtils.extractClientIp(request);

        Method method = ((MethodSignature) jp.getSignature()).getMethod();

        //接口参数
        Object[] params = jp.getArgs();

        //解析注入信息
        LogInject ann = method.getAnnotation(LogInject.class);

        // 执行返回
        boolean success = true;
        String log = "";
        Object objet = null;
        Exception e = null;
        try{
            objet = jp.proceed();
        }catch (Exception e1){
            e = e1;
            success = false;
            e.printStackTrace();
            log = e.getMessage();
        }


        // 从token中获得用户ID
        String userId = topLogService.currentUserId();

        // 登录响应参数
        if(this.isLogin(ann.logType()) && StringUtils.isBlank(userId) && success){
            ApiRest<SysUserLoginDTO> rest =  JSON.parseObject(JSON.toJSONString(objet), new TypeReference<ApiRest<SysUserLoginDTO>>(){});
            userId = rest.getData().getId();
        }

        // 保存日志，一定使用异步方法，避免阻塞主线程
        topLogService.saveLog(ann.logType(), uri, ann.title(), ip, userId, JSON.toJSONString(params), success, log);

        // 存在异常，抛出
        if(!success){
            throw e;
        }

        return objet;
    }

    /**
     * 是否登录接口
     * @param logType
     * @return
     */
    private boolean isLogin(String logType){
        if(!StringUtils.isBlank(logType) && "login".equals(logType)){
            return true;
        }
        return false;
    }

}
